﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using NRex.Logging;

namespace NRex
{
    public class AbstractReferencesLister
    {
        protected ILogger Logger { get; set; }
        protected List<Assembly> Assemblies = new List<Assembly>();

        protected AbstractReferencesLister(ILogger logger)
        {
            Logger = logger;
        }

        private static IEnumerable<string> GetAssemblyFiles(string fileOrDirectory)
        {
            IEnumerable<string> files = null;

            if (File.Exists(fileOrDirectory))
            {
                files = new List<string> {fileOrDirectory};
            }
            else
            {
                if (!Directory.Exists(fileOrDirectory))
                    return null;

                string[] extensions = {".dll", ".exe"};
                files = Directory.EnumerateFiles(fileOrDirectory, "*.*").Where(
                    file => extensions.Any(ext => ext == Path.GetExtension(file)));
            }

            return files;
        }

        protected void GetAssemblies(string fileOrDirectory)
        {
            var files = GetAssemblyFiles(fileOrDirectory);
            if (files == null)
            {
                Logger.Info("No dll or exe found for {0}", fileOrDirectory);
                return;
            }

            LoadAssemblies(files);
            if (Assemblies.Count() == 0)
            {
                Logger.Info("No .Net assembly found in {0}", fileOrDirectory);
                return;
            }
        }

        protected void LoadAssemblies(IEnumerable<string> files)
        {
            foreach (var file in files)
            {
                try
                {
                    Assemblies.Add(Assembly.LoadFrom(file));
                }
                catch (Exception)
                {
                    Logger.Info("Failed to load {0}", file);
                    continue;
                }
            }
        }
    }
}